﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Messaging;

using Microsoft.SensorServices.Rfid;
using Microsoft.SensorServices.Rfid.Dspi;
using System.IO.SensorServices.Rfid.Client;
using Microsoft.SensorServices.Rfid.Utilities;
using Microsoft.SensorServices.Rfid.ProcessComponents;
using Microsoft.SensorServices.Rfid.Design;

namespace BizTalk.RFID.EventHandlers
{
    public class MSMQSink : RfidEventHandlerBase
    {
        static RfidEventHandlerMetadata rfidEhmetadata;

        #region properties
        private string type = defaultType;
        const string defaultType = "csv";
        const string paramType = "Type";

        private string QueueName = defaultQueue;
        const string defaultQueue = "machinename\\private$\\QueueName";
        const string paramQueue = "QueueName";

        private string LabelName = defaultLabel;
        const string defaultLabel = "machine\\QueueName";
        const string paramLabel = "Label";

        private bool transactional = defaultTransactional;
        const bool defaultTransactional = true;
        const string paramTransactional = "Transacational";

       // string QueueName = "sudhirh1\\private$\\SudsQueue";
        //string LabelName = "private$\\SudsQueue";

        private MessageQueue MQ = null;
        


        #endregion
        public static RfidEventHandlerMetadata GetEventHandlerMetadata(bool getVendorExtensionsAlso)
        {
            try
            {

                RfidRuleEngineContext.LogError("In GetMetaData", null);

                if (rfidEhmetadata == null)
                {
                    Dictionary<string, RfidEventHandlerParameterMetadata> metadata = new Dictionary<string, RfidEventHandlerParameterMetadata>();

                    metadata.Add(paramQueue, new RfidEventHandlerParameterMetadata(typeof(string), "MSMQ Queue Name", defaultQueue, false));
                    metadata.Add(paramLabel, new RfidEventHandlerParameterMetadata(typeof(string), "MSMQ Label for Queue", defaultLabel, false));
                    metadata.Add(paramType, new RfidEventHandlerParameterMetadata(typeof(string), "Format of data csv or XML.", defaultType, false));
                    metadata.Add(paramTransactional, new RfidEventHandlerParameterMetadata(typeof(bool), "Transactional Queues", defaultTransactional, false));
                    rfidEhmetadata = new RfidEventHandlerMetadata("MSMQ Sink", metadata);
                }
                RfidRuleEngineContext.LogError("Out GetMetaData", null);
            }
            catch (Exception exc)
            {
            }
            return rfidEhmetadata;

        }

        /// <summary>
        /// This class is called to initialize the FileSink Event Handler
        /// </summary>
        /// <param name="parameters">parameters</param>
        /// <param name="container">container</param>
        public override void Init(Dictionary<string, object> parameters, RfidProcessContext container)
        {
            try
            {
                RfidRuleEngineContext.LogError("In Init", null);

                #region initialize parameters
                if (parameters != null)
                {
                    if (parameters.ContainsKey(paramQueue))
                        QueueName = (string)parameters[paramQueue];
                    if (parameters.ContainsKey(paramTransactional))
                        transactional = (bool)parameters[paramTransactional];
                    if (parameters.ContainsKey(paramLabel))
                        LabelName = (string)parameters[paramLabel];
                    if (parameters.ContainsKey(paramType))
                        type = (string)parameters[paramType];

                }
                else
                {
                    QueueName = defaultQueue;
                    LabelName = defaultLabel;
                    type = defaultType;
                    transactional = defaultTransactional;
                }
                #endregion

                if (!MessageQueue.Exists(QueueName))
                {
                    // create the new message queue and make it transactional
                    MQ = MessageQueue.Create(QueueName, transactional);

                    MQ.SetPermissions("Everyone", MessageQueueAccessRights.FullControl);

                    // set the label name and close the message queue
                    MQ.Label = LabelName;
                }
                else
                {
                    // create a message queue object
                    MQ = new MessageQueue(QueueName);

                }
                RfidRuleEngineContext.LogError("Out Init", null);
            }
            catch (Exception exc)
            {
            }

        }

        /// <summary>
        /// Called for every time a tag read hits the event handler.
        /// </summary>
        /// <param name="tagReadEvent">Tag Read Information</param>
        /// <returns>return tagread</returns>
        [RfidEventHandlerMethod]
        public RfidEventBase HandleTagReadEvent(RfidEventBase tagGenericReadEvent)
        {
            TagReadEvent tagReadEvent = null;
            try
            {
                try
                {
                    tagReadEvent = (TagReadEvent)tagGenericReadEvent;
                }
                catch (Exception exc)
                {
                    return null;
                }
                if (tagReadEvent == null){return tagReadEvent;}

                if (!(type.ToUpper().Equals("XML")))
                {
                    string strData = "" + HexUtilities.HexEncode(tagReadEvent.GetId()) + "," + tagReadEvent.DeviceName + "," + tagReadEvent.Source + "," + tagReadEvent.Time + "," + tagReadEvent.Type;

                    if (tagReadEvent.VendorSpecificData != null && tagReadEvent.VendorSpecificData.Count > 0)
                    {
                        foreach (string key in tagReadEvent.VendorSpecificData.Keys)
                        {
                            strData = strData + "," + key + "=" + tagReadEvent.VendorSpecificData[key];
                        }
                    }
                    SendMessage(strData);
                }
                else
                {
                    string strData = "<TagRead tagid=\"" + HexUtilities.HexEncode(tagReadEvent.GetId()) + "\" devicename=\"" + tagReadEvent.DeviceName + "\" source=\"" + tagReadEvent.Source + "\" time=\"" + tagReadEvent.Time + "\" type=\"" + tagReadEvent.Type + "\"";


                    if (tagReadEvent.VendorSpecificData != null && tagReadEvent.VendorSpecificData.Count > 0)
                    {
                        foreach (string key in tagReadEvent.VendorSpecificData.Keys)
                        {
                            strData = strData + " " + key + "=\"" + tagReadEvent.VendorSpecificData[key] + "\"";
                        }
                    }
                    strData = strData + " />";
                    SendMessage(strData);
                }


            }
            catch (Exception exc)
            {
            }
            return tagReadEvent;

        }

        [RfidEventHandlerMethod]
        public RfidEventBase[] HandleTagReadEvent(RfidEventBase[] tagGenericReadEvent)
        {
            foreach (RfidEventBase eventobj in tagGenericReadEvent)
            {
                HandleTagReadEvent(eventobj);
            }
            return tagGenericReadEvent;
        }

        /// <summary>
        /// Called to dispose the object.
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            try
            {
                base.Dispose(disposing);
                // close the mesage queue
                MQ.Close();
            }
            catch (Exception exc)
            {

            }
            finally
            {
                base.Dispose(disposing);
            }

        }


        private void SendMessage(string message)
        {
            
            // create the message and set the base properties
            Message Msg = new Message(message);
            //Msg.ResponseQueue = new MessageQueue(ResponseMessageQueuePath);
            Msg.Priority = MessagePriority.Normal;
            Msg.UseJournalQueue = true;
            Msg.Label = "Tag Read";

            // we want a acknowledgement if received or not in the response queue
            Msg.AcknowledgeType = AcknowledgeTypes.None;
            //Msg.AdministrationQueue = new MessageQueue(ResponseMessageQueuePath);

            // send the message
            if (transactional)
            {
                MessageQueueTransaction transaction = new MessageQueueTransaction();
                transaction.Begin();
                MQ.Send(Msg, transaction);
                transaction.Commit();
            }
            else
                MQ.Send(Msg);


        }

        // Methods
        public static EventHandlerDefinition CreateDefaultEventHandlerDefinition()
        {
            Type type = typeof(MSMQSink);
            string fullName = type.Assembly.FullName;
            string componentName = type.FullName;
            return new EventHandlerDefinition(componentName, new EventHandlerInfo(fullName, componentName));
        }

        public static void Deploy(Dictionary<string, object> parameters)
        {
        }
        public static void Undeploy(Dictionary<string, object> parameters)
        {
        }

    


    }
}
